package com.tbit.main.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbit.common.utils.TraceUtil;
import com.tbit.main.common.JsonResult;
import com.tbit.main.constant.SysConstant;
import com.tbit.main.dao.core.*;
import com.tbit.main.exception.BaseException;
import com.tbit.main.h2.pojo.ParkPoint;
import com.tbit.main.pojo.*;
import com.tbit.main.pojo.VO.DetentionVo;
import com.tbit.main.pojo.VO.WarehouseVo;
import com.tbit.main.service.*;
import com.tbit.main.util.GeoUtil;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import static com.tbit.main.constant.DaoParamConstant.accountId;

/**
 * @Author: chen
 * @Description:
 * @Date: 创建于 17:36 2023/2/7
 */
@Service
public class DetentionAreaServiceImpl extends ServiceImpl<DetentionAreaDao, DetentionArea> implements
        DetentionAreaService {

    @Autowired
    private DetentionAreaDao detentionAreaDao;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private DetentionMachineBoundService detentionMachineBoundService;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private MachineStatusDao machineStatusDao;
    @Autowired
    private MachineService machineService;

    @Override
    public JsonResult getByAccountId(Integer accountId, Integer mapType) {
/*        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("accountId", accountId);*/
        List<DetentionArea> list = detentionAreaDao.getByAccountId(accountId);
        list.forEach(detentionArea -> {
            calibrateService.calDetentionArea(detentionArea, SysConstant.ORIGINAL, mapType);
        });
        return JsonResult.succ(list);
    }

    @Override
    public JsonResult add(DetentionArea detentionArea, Integer mapType) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("accountId", detentionArea.getAccountId());
        List<DetentionArea> list = detentionAreaDao.selectList(queryWrapper);
        if (list != null && list.size()>100){
            return JsonResult.fail(500, "扣押区已经达到100上线", TraceUtil.getTraceIdByLocal());
        }
        if (!checkNameLength(detentionArea.getName())){
            return JsonResult.fail(500, "扣押区名称不得超过6个汉字",TraceUtil.getTraceIdByLocal());
        }
        if (detentionArea.getAllowRange() > 1000 ){
            return JsonResult.fail(500, "扣押区误差不能超过1000",TraceUtil.getTraceIdByLocal());
        }
        DetentionArea nearDetention = detentionAreaDao.getNearDetention(detentionArea.getAccountId(), detentionArea.getLo(), detentionArea.getLa());
        if (nearDetention != null){
            return JsonResult.fail(500, "扣押区名称不能重复",TraceUtil.getTraceIdByLocal());
        }
        detentionArea.setEnable(1);
        /**校准*/
        calibrateService.calDetentionArea(detentionArea, mapType, SysConstant.ORIGINAL);
        detentionAreaDao.insert(detentionArea);
        return JsonResult.succ();
    }

    @Override
    public JsonResult edit(DetentionArea detentionArea, Integer mapType) {
        DetentionArea detentionByName = detentionAreaDao.getDetentionByName(detentionArea.getAccountId(),detentionArea.getDetentionId(),detentionArea.getName());
        if (detentionByName != null && detentionByName.getDetentionId() != detentionArea.getDetentionId()){
            return JsonResult.fail(500, "扣押区名称重复",TraceUtil.getTraceIdByLocal());
        }
        DetentionArea nearDetention = detentionAreaDao.getNearDetention(detentionArea.getAccountId(), detentionArea.getLo(), detentionArea.getLa());
        if (nearDetention != null && nearDetention.getDetentionId() != detentionArea.getDetentionId()){
            return JsonResult.fail(500, "扣押区定位重复",TraceUtil.getTraceIdByLocal());
        }
        if (!checkNameLength(detentionArea.getName())){
            return JsonResult.fail(500, "扣押区名称不得超过6个汉字",TraceUtil.getTraceIdByLocal());
        }
        DetentionArea detentionAreaDB = detentionAreaDao.selectById(detentionArea.getDetentionId());
        if (detentionAreaDB == null) {
            throw new BaseException("detentionArea.not.exist");
        }
        detentionArea.setAccountId(detentionArea.getAccountId());
        /**校准*/
        calibrateService.calDetentionArea(detentionArea, mapType, SysConstant.ORIGINAL);
        //修改仓库名字的同时把入库相关联的也修改了
        UpdateWrapper<DetentionMachineBound> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("detentionId", detentionArea.getDetentionId());
        updateWrapper.set("detentionName", detentionArea.getName());
        detentionMachineBoundService.update(updateWrapper);
        detentionAreaDao.updateById(detentionArea);
        return JsonResult.succ();
    }

    @Override
    public List<DetentionVo> getAllDetention(Integer accountId ) {
        return detentionAreaDao.getAllDetention(accountId);
    }

    @Override
    public DetentionArea getNearDetention(Integer accountId, Double lo, Double la,String name) {
        return detentionAreaDao.getNearDetention(accountId,lo,la);
    }

    @Override
    public JsonResult getNear(String userCodeS, Integer mapType,Integer accountId) {
        HashMap<String, Object> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("userCodes",userCodeS);
        String[] split = userCodeS.split(",");
        List<String> UserCodeList = Arrays.asList(split);
        List<Machine> byUserCodes = machineDao.getByUserCodeList(UserCodeList);
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        double minDistance = Double.MAX_VALUE;
        DetentionArea detentionArea = null;
        /**默认谷歌地图*/
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }
        for (Machine byUseCodeMachine : byUserCodes) {
            if (byUseCodeMachine != null){
                MachineStatus byMachineId = machineStatusDao.getByMachineId(byUseCodeMachine.getMachineId());
                if (byMachineId == null ){
                    continue;
                }
                List<DetentionArea> near = detentionAreaDao.getByAccountId(accountId);
                if (near == null || Objects.equals(0,near.size())){
                    continue;
                }
                Point point = new Point(byMachineId.getLon(), byMachineId.getLat());
                // 遍历列表找到最近的 DetentionArea 对象
                for (DetentionArea detentionAreaItem : near) {

                    /** 检验距离有效性,车辆位置跟站点距离不能超出设定的值才认为有效 */
                    List<Point> points = GeoUtil.getPoints(detentionAreaItem.getPoints());
                    /** 判断是否在多边形内 */
                    if (!GeoUtil.IsPtInPoly(point, points)) {
                        Integer allowRange = detentionAreaItem.getAllowRange();
                        Double distince = GeoUtil.getDistance(point, points);
                        if (distince > allowRange) {
                          continue;
                        }else {
                           if (distince < minDistance){
                               minDistance = distince;
                               detentionArea = detentionAreaItem;
                           }
                        }
                    }else {
                        detentionArea = detentionAreaItem;
                        break;
                    }
                }
                if (detentionArea != null){
                    calibrateService.calDetentionArea(detentionArea, SysConstant.ORIGINAL, mapType);
                    return JsonResult.succ(detentionArea);
                }

            }
        }
        stringObjectHashMap.put("status",0);
        stringObjectHashMap.put("msg","车辆附近没有扣押区");
       return JsonResult.succ(stringObjectHashMap);
    }

    @Override
    public JsonResult checkNear(String userCodeS, Integer mapType,Integer accountId,Integer detentionId) {
        HashMap<String, Object> returnMap = new HashMap<>();
        DetentionArea byDetentionId = detentionAreaDao.getByDetentionId(detentionId);
        ArrayList<String> noMachine = new ArrayList<>();// 不存在的车
        ArrayList<Machine> noNear = new ArrayList<>();// 不在推荐点的车
        ArrayList<Machine> yesNear = new ArrayList<>();// 在推荐点的车
        ArrayList<Machine> notNear = new ArrayList<>();// 没有推荐点的车
        String[] split = userCodeS.split(",");
        List<String> userCodeList = Arrays.asList(split);
        for (String useCode : split) {
            Machine machine = machineService.getByUseCode(useCode);
            if (machine == null) {
                noMachine.add(useCode);
            }
        }
        HashMap<String, Object> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("userCodes",userCodeS);
        List<Machine> byUserCodes = machineDao.getByUserCodeList(userCodeList);
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        double minDistance = Double.MAX_VALUE;
        /**默认谷歌地图*/
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }
        for (Machine byUseCodeMachine : byUserCodes) {
            if (!byUseCodeMachine.getAccountId().equals(accountId)) {
                //不在当前区域的车辆也标记为车辆不存在
                noMachine.add(byUseCodeMachine.getUserCode());
                continue;
            }
            DetentionArea detentionArea = null;
            if (byUseCodeMachine != null){
                MachineStatus byMachineId = machineStatusDao.getByMachineId(byUseCodeMachine.getMachineId());
                if (byMachineId == null ){
                    continue;
                }
                //给车辆定位
                byUseCodeMachine.setLon( byMachineId.getLon());
                byUseCodeMachine.setLat( byMachineId.getLat());
                /** 校准 */
                calibrateService.calibrateMachined(byUseCodeMachine, mapType);
                Point point = new Point(byMachineId.getLon(), byMachineId.getLat());

                /** 检验距离有效性,车辆位置跟站点距离不能超出设定的值才认为有效 */
                List<Point> points = GeoUtil.getPoints(byDetentionId.getPoints());
                /** 判断是否在多边形内 */
                if (!GeoUtil.IsPtInPoly(point, points)) {
                    Integer allowRange = byDetentionId.getAllowRange();
                    Double distince = GeoUtil.getDistance(point, points);
                    if (distince >= allowRange) {
                        notNear.add(byUseCodeMachine);
                        continue;
                    }
                }

 /*               List<DetentionArea> near = detentionAreaDao.getNear(byMachineId.getLat(), byMachineId.getLon(), accountId);
                if (near == null || Objects.equals(0,near.size())){
                    //如果没有找到最近扣押区,
                    notNear.add(byUseCodeMachine);
                    continue;
                }
                // 遍历列表找到最近的 DetentionArea 对象
                for (DetentionArea detentionAreaItem : near) {
                    double latDiff = detentionAreaItem.getLa() - byMachineId.getLat();
                    double lonDiff = detentionAreaItem.getLo() - byMachineId.getLon();
                    double distance = Math.sqrt(latDiff * latDiff + lonDiff * lonDiff);
                    if (distance < minDistance) {
                        minDistance = distance;
                        detentionArea = detentionAreaItem;
                    }
                }*/
                yesNear.add(byUseCodeMachine);


            }

        }
        calibrateService.calDetentionArea(byDetentionId, SysConstant.ORIGINAL, mapType);
        returnMap.put("detentionArea",byDetentionId);
        returnMap.put("noMachine",noMachine);
        returnMap.put("noNear",noNear);
        returnMap.put("yesNear",yesNear);
        returnMap.put("notNear",notNear);
        return JsonResult.succ(returnMap);
    }

    @Override
    public JsonResult getByDetentionId(Integer detentionId, Integer mapType) {
/*        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("accountId", accountId);*/
        DetentionArea byDetentionId = detentionAreaDao.getByDetentionId(detentionId);
        calibrateService.calDetentionArea(byDetentionId, SysConstant.ORIGINAL, mapType);
        return JsonResult.succ(byDetentionId);
    }

    @Override
    public DetentionArea getByDetentionAreaName(Integer accountId, String detentionAreaName) {
        return detentionAreaDao.getByDetentionAreaName(accountId, detentionAreaName);
    }

    /*    @Override
    public DetentionArea getNearDetention(Integer accountId, Double lo, Double la,String name) {
        return detentionAreaDao.getNearDetention(accountId,lo,la,name);
    }*/


    // 检查名称长度是否符合要求
    public boolean checkNameLength(String name) {
        // 计算汉字数量
        int chineseCharCount = 0;
        for (int i = 0; i < name.length(); i++) {
            char c = name.charAt(i);
            if (c >= 0x4e00 && c <= 0x9fa5) {
                chineseCharCount++;
            }
        }

        // 判断是否超过限制
        return name.length() <= 12 && chineseCharCount <= 6;
    }



}
